<?php
include_once "lib/Utils.php";
include_once "lib/Http/Session.php";
include_once "lib/Http/Cookie.php";
include_once "lib/IO/UploadFile.php";

class Request{
    private string $method;
    private string $uri;
    private $headers;
    private array $parameters;
    /**
     * @var ?string 请求类型
     */
    private ?string $contentType;

    /**
     * @var string 字符集
     */
    private string $charset;
    /**
     * @var array<UploadFile> 上传的文件列表
     */
    private array $files;
    private $originBody;
    private Session $session;

    /**
     * @var array<Cookie> cookie列表
     */
    private array $cookies;


    public function __construct() {
        // 获取请求方法
        $this->method = $_SERVER['REQUEST_METHOD'];
        // 获取所有请求投
        $this->headers = getallheaders();
        // 获取路径
        $this->uri = explode("?",$_SERVER['REQUEST_URI'])[0];
        // 获取参数
        $this->parameters = array_merge($_GET, $_POST);
        // 获取请求Content-type
        $this->contentType = $this->getHeader('Content-Type');
        //处理上传的文件
        $this->files = $this->handleFiles();
        // 保存源请求体
        $this->originBody = file_get_contents("php://input");
        // 获取Session
        $this->session = new Session();
        // 获取Cookies
        $this->cookies = $this->parseCookie();
    }

    private function handleFiles():array{
        $files = [];
        foreach ($_FILES as $name => $file) {
            $files[$name] = new UploadFile($file);
        }
        return $files;
    }

    private function parseCookie():array{
        $arr = array();
        foreach ($_COOKIE as $key => $value){
            $arr[] = new Cookie($key,$value);
        }
        return $arr;
    }

    /**
     * 解析get参数,post请求也必须执行
     * @return array
     */
    private function parseGetQueryString():array{
        // 如果参数为空
        if (empty($_GET)){
            $this->uri = "/";
            return [];
        }
        $ret = array_merge([],$_GET);
        $queryKey = array_keys($_GET);
        $firstParamKey = $queryKey[0];
        $firstParamValue = $_GET[$firstParamKey];
        // 获取路径和第一个参数的key
        // 以/开头视为路径
        if (Utils::String_startWith($firstParamKey,"/")){
            $childParams = explode("?",$firstParamKey);
            if (count($childParams) == 1){ //分割后只有一个说明后面没有参数了
                $this->uri = $childParams[0];
                // 删除原本的
                unset($ret[$firstParamKey]);
            }elseif (count($childParams) > 1){ //只有大于1了才表示有第一个参数
                $this->uri = $childParams[0];
                // 删除原本的
                unset($ret[$firstParamKey]);
                // 添加解析后的key和value
                $ret = array_merge([$childParams[1]=>$firstParamValue],$ret);
            }
        }elseif(Utils::String_startWith($firstParamKey,"?")){//以问号开头说明没有路径直接是参数，这时候默认路径是/
            //不以/开头视为参数，且路径为/
            $this->uri = "/";
            unset($ret[$firstParamKey]);
            $ret = array_merge([substr($firstParamKey,1)=>$firstParamValue],$ret);
        }else{ //都不是
            $this->uri = "/";
        }
        return $ret;
    }

    public function getMethod() {
        return $this->method;
    }

    public function isGETMethod(){
        return $this->method === "GET";
    }
    public function isPOSTMethod(){
        return $this->method === "POST";
    }

    public function getUri() {
        return $this->uri;
    }

    public function getHeader($name) {
        if (isset($this->headers[$name])){
            return $this->headers[$name];
        }else{
            return null;
        }
    }

    public function getParameter($name) {
        return $this->parameters[$name] ?? null;
    }

    public function getParameters() {
        return $this->parameters;
    }
    public function getContentType() {
        return $this->contentType;
    }

    /**
     * 获取接受的文件类型
     * @return mixed
     */
    public function getAccept(){
        return $this->getHeader("Accept");
    }

    public function getQueryString() {
        return $_SERVER['QUERY_STRING'];
    }

    public function getSession():Session {
        return $this->session;
    }

    /**
     * @return array<Cookie>
     */
    public function getCookie():array{
        return $this->cookies;
    }
}